package danran.dbapi.controller;

import danran.dbapi.common.ResponseDto;
import danran.dbapi.domain.Plugin;
import danran.dbapi.plugin.PluginConf;
import danran.dbapi.plugin.loader.PluginClassLoader;
import danran.dbapi.service.PluginService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @Classname PluginController
 * @Description TODO
 * @Date 2022/2/8 21:03
 * @Created by RanCoder
 */
@RestController
@RequestMapping("/plugin")
public class PluginController {
    private static final Logger log = LoggerFactory.getLogger(PluginController.class);
    @Autowired
    private PluginService pluginService;

    @Autowired
    private PluginClassLoader loader;

    /**
     * 用户上传自定义插件文件
     *
     * @param files      上传的批量文件
     * @param name       插件名称
     * @param note       插件描述
     * @param classname  插件的主类的全类名
     * @param param_desc 插件需要的参数
     * @return 响应
     */
    @RequestMapping("/upload")
    public ResponseDto uploadPluginFile(@RequestParam("files") MultipartFile[] files,
                                        @RequestParam("name") String name,
                                        @RequestParam("note") String note,
                                        @RequestParam("classname") String classname,
                                        @RequestParam("param_desc") String param_desc) throws ClassNotFoundException, IllegalAccessException, InstantiationException, IOException {
        if (files == null || files.length == 0) {
            return ResponseDto.fail("请选择文件!");
        }

        StringBuilder pluginFiles = new StringBuilder();

        for (MultipartFile file : files) {
            // 源文件名称
            String originalFilename = file.getOriginalFilename();
            // 文件格式
            assert originalFilename != null;
            String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
            // 新文件名，避免文件名重复
            String fileName = UUID.randomUUID() + suffix;
            // 文件存储路径
            String targetPath = PluginConf.getKey("plugin.targetPath");
//            String targetPath = "./plugin_files/";
            // 根据文件后缀分类加载
            if (suffix.equals(".class")) {
                targetPath += "classes/";
            } else if (suffix.equals(".jar")) {
                targetPath += "lib/";
            } else {
                return ResponseDto.fail("不支持该格式的文件");
            }
            pluginFiles.append(targetPath).append(fileName).append(";");
            // 构建目标文件对象
            File targetFile = new File(targetPath + fileName);
            // 目录不存在就创建
            if (!targetFile.getParentFile().exists()) {
                boolean s = targetFile.getParentFile().mkdir();
                if (!s) {
                    return ResponseDto.fail("文件目录创建失败");
                }
            }
            try {
                // 文件存储
                file.transferTo(targetFile);
            } catch (IOException e) {
                e.printStackTrace();
                return ResponseDto.fail("文件上传失败，请稍后再试。");
            }
            loader.addJar(targetFile);
        }
//        PluginClassLoader loader = new PluginClassLoader(PluginConf.getKey("plugin.targetPath"));
        log.info("相关jar包的类已经加载");
//        Class<?> clazz = loader.loadClass("demo.EncryptTransformerPlugin");
//        TransformerPlugin instance = (TransformerPlugin) clazz.newInstance();
//        List<JSONObject> d = new ArrayList<>();
//        JSONObject jsonObject = new JSONObject();
//        jsonObject.put("num", "123456789");
//        d.add(jsonObject);
//        instance.transform(d, "num");
//        System.out.println(d.get(0).toJSONString());
        Plugin plugin = new Plugin().setName(name)
                .setNote(note).setClassname(classname)
                .setParam_desc(param_desc)
                .setFiles(pluginFiles.toString());
        pluginService.addPlugin(plugin);
        return ResponseDto.successWithMsg("插件上传成功！");
    }

    @RequestMapping("/getPlugins")
    public ResponseDto getPlugins() {
        List<Plugin> allPlugins = pluginService.getAllPlugins();
        if (allPlugins == null) {
            return ResponseDto.fail("获取插件数据失败");
        }
        return ResponseDto.successWithData(allPlugins);
    }

    @RequestMapping("/delete/{id}")
    public ResponseDto deletePluginById(@PathVariable("id") int id) {
        try {
            Plugin plugin = pluginService.getPlugin(id);
            if (plugin.getIn_use() != 0) {
                return ResponseDto.fail("仍有API使用该插件，删除失败.");
            }
            pluginService.deletePlugin(id);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseDto.fail(e.toString());
        }
        return ResponseDto.successWithMsg("删除插件成功");
    }

    @RequestMapping("/getPluginMapNameToId")
    public ResponseDto getPluginMapNameToId() {
        Map<String, Integer> map = pluginService.getPluginMapNameToId();
        if (map != null) {
            return ResponseDto.successWithData(map);
        }
        return ResponseDto.fail("获取插件映射表-Name-Id出错");
    }
}
